home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / win / wgraph.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-19  |  46.0 KB  |  1,668 lines

  1. #ifndef lint ß
  2. 4-9$¸$Sid = "$Id: wgraph.c,v 1.5.2.1 1999/08/19 14:13:09 lhecking Exp $";
  3. #endif
  4.  
  5. /* GNUPLOT - win/wgraph.c */
  6. /*[
  7.  * Copyright 1992, 1993, 1998   Maurice Castro, Russell Lang
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and
  12.  * that both that copyright notice and this permission notice appear
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the complete modified source code.  Modifications are to
  17.  * be distributed as patches to the released version.  Permission to
  18.  * distribute binaries produced by compiling modified sources is granted,
  19.  * provided you
  20.  *   1. distribute the corresponding source modifications from the
  21.  *    released version in the form of a patch file along with the binaries,
  22.  *   2. add special version identification to distinguish your version
  23.  *    in addition to the base release version number,
  24.  *   3. provide your name and address as the primary contact for the
  25.  *    support of your modified version, and
  26.  *   4. retain our contact information in regard to use of the base
  27.  *    software.
  28.  * Permission to distribute the released version of the source code along
  29.  * with corresponding source modifications in the form of a patch file is
  30.  * granted with same provisions 2 through 4 for binary distributions.
  31.  *
  32.  * This software is provided "as is" without express or implied warranty
  33.  * to the extent permitted by applicable law.
  34. ]*/
  35.  
  36. /*
  37.  * AUTHORS
  38.  * 
  39.  *   Maurice Castro
  40.  *   Russell Lang
  41.  * 
  42.  * Send your comments or suggestions to 
  43.  *  info-gnuplot@dartmouth.edu.
  44.  * This is a mailing list; to join it send a note to 
  45.  *  majordomo@dartmouth.edu.  
  46.  * Send bug reports to
  47.  *  bug-gnuplot@dartmouth.edu.
  48.  */
  49.  
  50. #define STRICT
  51. #include <windows.h>
  52. #include <windowsx.h>
  53. #if WINVER >= 0x030a
  54. #include <commdlg.h>
  55. #endif
  56. #ifndef __MSC__
  57. #include <mem.h>
  58. #endif
  59. #include <stdio.h>
  60. #include <string.h>
  61. #include "wgnuplib.h"
  62. #include "wresourc.h"
  63. #include "wcommon.h"
  64.  
  65. LRESULT CALLBACK WINEXPORT WndGraphProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  66.  
  67. void ReadGraphIni(LPGW lpgw);
  68.  
  69. /* ================================== */
  70.  
  71. #define MAXSTR 255
  72.  
  73. #define WGDEFCOLOR 15
  74. COLORREF wginitcolor[WGDEFCOLOR] =  {
  75.     RGB(255,0,0),    /* red */
  76.     RGB(0,255,0),    /* green */
  77.     RGB(0,0,255),    /* blue */
  78.     RGB(255,0,255), /* magenta */
  79.     RGB(0,0,128),    /* dark blue */
  80.     RGB(128,0,0),    /* dark red */
  81.     RGB(0,128,128),    /* dark cyan */
  82.     RGB(0,0,0),    /* black */
  83.     RGB(128,128,128), /* grey */
  84.     RGB(0,128,64),    /* very dark cyan */
  85.     RGB(128,128,0), /* dark yellow */
  86.     RGB(128,0,128),    /* dark magenta */
  87.     RGB(192,192,192), /* light grey */
  88.     RGB(0,255,255),    /* cyan */
  89.     RGB(255,255,0),    /* yellow */
  90. };
  91. #define WGDEFSTYLE 5
  92. int wginitstyle[WGDEFSTYLE] = {PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT};
  93.  
  94. /* ================================== */
  95.  
  96. /* destroy memory blocks holding graph operations */
  97. void
  98. DestroyBlocks(LPGW lpgw)
  99. {
  100.     struct GWOPBLK *this, *next;
  101.     struct GWOP FAR *gwop;
  102.     unsigned int i;
  103.  
  104.     this = lpgw->gwopblk_head;
  105.     while (this != NULL) {
  106.         next = this->next;
  107.         if (!this->gwop) {
  108.             this->gwop = (struct GWOP FAR *)GlobalLock(this->hblk);
  109.         }
  110.         if (this->gwop) {
  111.             /* free all text strings within this block */
  112.             gwop = this->gwop;
  113.             for (i=0; i<GWOPMAX; i++) {
  114.                 if (gwop->htext)
  115.                     LocalFree(gwop->htext);
  116.                 gwop++;
  117.             }
  118.         }
  119.         GlobalUnlock(this->hblk);
  120.         GlobalFree(this->hblk);
  121.         LocalFreePtr(this);
  122.         this = next;
  123.     }
  124.     lpgw->gwopblk_head = NULL;
  125.     lpgw->gwopblk_tail = NULL;
  126.     lpgw->nGWOP = 0;
  127. }
  128.         
  129.     
  130. /* add a new memory block for graph operations */
  131. /* returns TRUE if block allocated */
  132. BOOL 
  133. AddBlock(LPGW lpgw)
  134. {
  135. HGLOBAL hblk;
  136. struct GWOPBLK *next, *this;
  137.  
  138.     /* create new block */
  139.     next = (struct GWOPBLK *)LocalAllocPtr(LHND, sizeof(struct GWOPBLK) );
  140.     if (next == NULL)
  141.         return FALSE;
  142.     hblk = GlobalAlloc(GHND, GWOPMAX*sizeof(struct GWOP));
  143.     if (hblk == NULL)
  144.         return FALSE;
  145.     next->hblk = hblk;
  146.     next->gwop = (struct GWOP FAR *)NULL;
  147.     next->next = (struct GWOPBLK *)NULL;
  148.     next->used = 0;
  149.     
  150.     /* attach it to list */
  151.     this = lpgw->gwopblk_tail;
  152.     if (this == NULL) {
  153.         lpgw->gwopblk_head = next;
  154.     }
  155.     else {
  156.         this->next = next;
  157.         this->gwop = (struct GWOP FAR *)NULL;
  158.         GlobalUnlock(this->hblk);
  159.     }
  160.     lpgw->gwopblk_tail = next;
  161.     next->gwop = (struct GWOP FAR *)GlobalLock(next->hblk);
  162.     if (next->gwop == (struct GWOP FAR *)NULL)
  163.         return FALSE;
  164.         
  165.     return TRUE;
  166. }
  167.  
  168.  
  169. void WDPROC
  170. GraphOp(LPGW lpgw, WORD op, WORD x, WORD y, LPSTR str)
  171. {
  172.     struct GWOPBLK *this;
  173.     struct GWOP FAR *gwop;
  174.     char *npstr;
  175.     
  176.     this = lpgw->gwopblk_tail;
  177.     if ( (this==NULL) || (this->used >= GWOPMAX) ) {
  178.         /* not enough space so get new block */
  179.         if (!AddBlock(lpgw))
  180.             return;
  181.         this = lpgw->gwopblk_tail;
  182.     }
  183.     gwop = &this->gwop[this->used];
  184.     gwop->op = op;
  185.     gwop->x = x;
  186.     gwop->y = y;
  187.     gwop->htext = 0;
  188.     if (str) {
  189.         gwop->htext = LocalAlloc(LHND, _fstrlen(str)+1);
  190.         npstr = LocalLock(gwop->htext);
  191.         if (gwop->htext && (npstr != (char *)NULL))
  192.             lstrcpy(npstr, str);
  193.         LocalUnlock(gwop->htext);
  194.     }
  195.     this->used++;
  196.     lpgw->nGWOP++;
  197.     return;
  198. }
  199.  
  200. /* ================================== */
  201.  
  202. void WDPROC
  203. GraphInit(LPGW lpgw)
  204. {
  205.     HMENU sysmenu;
  206.     WNDCLASS wndclass;
  207.     char buf[80];
  208.  
  209.     if (!lpgw->hPrevInstance) {
  210.         wndclass.style = CS_HREDRAW | CS_VREDRAW;
  211.         wndclass.lpfnWndProc = WndGraphProc;
  212.         wndclass.cbClsExtra = 0;
  213.         wndclass.cbWndExtra = 2 * sizeof(void FAR *);
  214.         wndclass.hInstance = lpgw->hInstance;
  215.         wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  216.         wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  217.         wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  218.         wndclass.lpszMenuName = NULL;
  219.         wndclass.lpszClassName = szGraphClass;
  220.         RegisterClass(&wndclass);
  221.     }
  222.  
  223.     ReadGraphIni(lpgw);
  224.  
  225.     lpgw->hWndGraph = CreateWindow(szGraphClass, lpgw->Title,
  226.         WS_OVERLAPPEDWINDOW,
  227.         lpgw->Origin.x, lpgw->Origin.y,
  228.         lpgw->Size.x, lpgw->Size.y,
  229.         NULL, NULL, lpgw->hInstance, lpgw);
  230.  
  231.     lpgw->hPopMenu = CreatePopupMenu();
  232.     AppendMenu(lpgw->hPopMenu, MF_STRING | (lpgw->graphtotop ? MF_CHECKED : MF_UNCHECKED), 
  233.         M_GRAPH_TO_TOP, "Bring to &Top");
  234.     AppendMenu(lpgw->hPopMenu, MF_STRING | (lpgw->color ? MF_CHECKED : MF_UNCHECKED), 
  235.         M_COLOR, "C&olor");
  236.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_COPY_CLIP, "&Copy to Clipboard");
  237. #if WINVER >= 0x030a
  238.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_BACKGROUND, "&Background...");
  239.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_CHOOSE_FONT, "Choose &Font...");
  240.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_LINESTYLE, "&Line Styles...");
  241. #endif
  242.     AppendMenu(lpgw->hPopMenu, MF_STRING, M_PRINT, "&Print...");
  243.     if (lpgw->IniFile != (LPSTR)NULL) {
  244.         wsprintf(buf,"&Update %s",lpgw->IniFile);
  245.         AppendMenu(lpgw->hPopMenu, MF_STRING, M_WRITEINI, (LPSTR)buf);
  246.     }
  247.  
  248.     /* modify the system menu to have the new items we want */
  249.     sysmenu = GetSystemMenu(lpgw->hWndGraph,0);
  250.     AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
  251.     AppendMenu(sysmenu, MF_POPUP, (UINT)lpgw->hPopMenu, "&Options");
  252.     AppendMenu(sysmenu, MF_STRING, M_ABOUT, "&About");
  253.  
  254.     if (!IsWindowVisible(lpgw->lptw->hWndParent)) {
  255.         AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
  256.         AppendMenu(sysmenu, MF_STRING, M_COMMANDLINE, "C&ommand Line");
  257.     }
  258.  
  259.     ShowWindow(lpgw->hWndGraph, SW_SHOWNORMAL);
  260. }
  261.  
  262. /* close a graph window */
  263. void WDPROC
  264. GraphClose(LPGW lpgw)
  265. {
  266.     /* close window */
  267.     if (lpgw->hWndGraph)
  268.         DestroyWindow(lpgw->hWndGraph);
  269.     TextMessage();
  270.     lpgw->hWndGraph = NULL;
  271.  
  272.     lpgw->locked = TRUE;
  273.     DestroyBlocks(lpgw);
  274.     lpgw->locked = FALSE;
  275.  
  276. }
  277.     
  278.  
  279. void WDPROC
  280. GraphStart(LPGW lpgw, double pointsize)
  281. {
  282.     lpgw->locked = TRUE;
  283.     DestroyBlocks(lpgw);
  284.         lpgw->org_pointsize = pointsize;
  285.     if ( !lpgw->hWndGraph || !IsWindow(lpgw->hWndGraph) )
  286.         GraphInit(lpgw);
  287.     if (IsIconic(lpgw->hWndGraph))
  288.         ShowWindow(lpgw->hWndGraph, SW_SHOWNORMAL);
  289.     if (lpgw->graphtotop)
  290.         BringWindowToTop(lpgw->hWndGraph);
  291.  
  292. }
  293.         
  294. void WDPROC
  295. GraphEnd(LPGW lpgw)
  296. {
  297. RECT rect;
  298.     GetClientRect(lpgw->hWndGraph, &rect);
  299.     InvalidateRect(lpgw->hWndGraph, (LPRECT) &rect, 1);
  300.     lpgw->locked = FALSE;
  301.     UpdateWindow(lpgw->hWndGraph);
  302. }
  303.  
  304. void WDPROC
  305. GraphResume(LPGW lpgw)
  306. {
  307.         lpgw->locked = TRUE;
  308. }
  309.  
  310. void WDPROC
  311. GraphPrint(LPGW lpgw)
  312. {
  313.     if (lpgw->hWndGraph && IsWindow(lpgw->hWndGraph))
  314.         SendMessage(lpgw->hWndGraph,WM_COMMAND,M_PRINT,0L);
  315. }
  316.  
  317. void WDPROC
  318. GraphRedraw(LPGW lpgw)
  319. {
  320.     if (lpgw->hWndGraph && IsWindow(lpgw->hWndGraph))
  321.         SendMessage(lpgw->hWndGraph,WM_COMMAND,M_REBUILDTOOLS,0L);
  322. }
  323. /* ================================== */
  324.  
  325. void
  326. StorePen(LPGW lpgw, int i, COLORREF ref, int colorstyle, int monostyle)
  327. {
  328.     LOGPEN FAR *plp;
  329.  
  330.     plp = &lpgw->colorpen[i];
  331.     plp->lopnColor = ref;
  332.     if (colorstyle < 0) {
  333.         plp->lopnWidth.x = -colorstyle;
  334.         plp->lopnStyle = 0;
  335.     }
  336.     else {
  337.         plp->lopnWidth.x = 1;
  338.         plp->lopnStyle = colorstyle % 5;
  339.     }
  340.     plp->lopnWidth.y = 0;
  341.  
  342.     plp = &lpgw->monopen[i];
  343.     plp->lopnColor = RGB(0,0,0);
  344.     if (monostyle < 0) {
  345.         plp->lopnWidth.x = -monostyle;
  346.             plp->lopnStyle = 0;
  347.     }
  348.     else {
  349.         plp->lopnWidth.x = 1;
  350.         plp->lopnStyle = monostyle % 5;
  351.     }
  352.     plp->lopnWidth.y = 0;
  353. }
  354.  
  355. void
  356. MakePens(LPGW lpgw, HDC hdc)
  357. {
  358.     int i;
  359.  
  360.     if ((GetDeviceCaps(hdc,NUMCOLORS) == 2) || !lpgw->color) {
  361.         /* Monochrome Device */
  362.         /* create border pens */
  363.         lpgw->hbpen = CreatePenIndirect((LOGPEN FAR *)&lpgw->monopen[0]);    /* border */
  364.         lpgw->hapen = CreatePenIndirect((LOGPEN FAR *)&lpgw->monopen[1]);     /* axis */
  365.         /* create drawing pens */
  366.         for (i=0; i<WGNUMPENS; i++)
  367.         {
  368.             lpgw->hpen[i] = CreatePenIndirect((LOGPEN FAR *)&lpgw->monopen[i+2]);
  369.             }
  370.         /* find number of solid, unit width line styles */
  371.         for (i=0; i<WGNUMPENS && lpgw->monopen[i+2].lopnStyle==PS_SOLID
  372.             && lpgw->monopen[i+2].lopnWidth.x==1; i++) ;
  373.         lpgw->numsolid = i ? i : 1;    /* must be at least 1 */
  374.         lpgw->hbrush = CreateSolidBrush(RGB(255,255,255));
  375.         for (i=0; i<WGNUMPENS+2; i++) 
  376.                 lpgw->colorbrush[i] = CreateSolidBrush(RGB(0,0,0));
  377.     }
  378.     else {
  379.         /* Color Device */
  380.         /* create border pens */
  381.         lpgw->hbpen = CreatePenIndirect((LOGPEN FAR *)&lpgw->colorpen[0]);    /* border */
  382.         lpgw->hapen = CreatePenIndirect((LOGPEN FAR *)&lpgw->colorpen[1]);     /* axis */
  383.         /* create drawing pens */
  384.         for (i=0; i<WGNUMPENS; i++)
  385.         {
  386.             lpgw->hpen[i] = CreatePenIndirect((LOGPEN FAR *)&lpgw->colorpen[i+2]);
  387. #if 1 /* HBB 980118 fix 'numsolid' problem */
  388.             lpgw->hsolidpen[i] = CreatePen(PS_SOLID, 1, lpgw->colorpen[i+2].lopnColor);
  389. #endif
  390.             }
  391.         /* find number of solid, unit width line styles */
  392.         for (i=0; i<WGNUMPENS && lpgw->colorpen[i+2].lopnStyle==PS_SOLID
  393.             && lpgw->colorpen[i+2].lopnWidth.x==1; i++) ;
  394.         lpgw->numsolid = i ? i : 1;    /* must be at least 1 */
  395.         lpgw->hbrush = CreateSolidBrush(lpgw->background);
  396.         for (i=0; i<WGNUMPENS+2; i++) 
  397.                 lpgw->colorbrush[i] = CreateSolidBrush(lpgw->colorpen[i].lopnColor);
  398.     }
  399. }
  400.  
  401. void
  402. DestroyPens(LPGW lpgw)
  403. {
  404.     int i;
  405.  
  406.     DeleteObject(lpgw->hbrush);
  407.     DeleteObject(lpgw->hbpen);
  408.     DeleteObject(lpgw->hapen);
  409.     for (i=0; i<WGNUMPENS; i++)
  410.         DeleteObject(lpgw->hpen[i]);
  411. #if 1 /* HBB 980118: fix 'numsolid' gotcha */
  412.     for (i=0; i<WGNUMPENS; i++)
  413.         DeleteObject(lpgw->hsolidpen[i]);
  414. #endif
  415.     for (i=0; i<WGNUMPENS+2; i++)
  416.         DeleteObject(lpgw->colorbrush[i]);
  417. }
  418.  
  419. /* ================================== */
  420.  
  421. void
  422. MakeFonts(LPGW lpgw, LPRECT lprect, HDC hdc)
  423. {
  424.     LOGFONT lf;
  425.     HFONT hfontold;
  426.     TEXTMETRIC tm;
  427.     int result;
  428.     char FAR *p;
  429.     int cx, cy;
  430.  
  431.     lpgw->rotate = FALSE;
  432.     _fmemset(&lf, 0, sizeof(LOGFONT));
  433.     _fstrncpy(lf.lfFaceName,lpgw->fontname,LF_FACESIZE);
  434.     lf.lfHeight = -MulDiv(lpgw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  435.     lf.lfCharSet = DEFAULT_CHARSET;
  436.     if ( (p = _fstrstr(lpgw->fontname," Italic")) != (LPSTR)NULL ) {
  437.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  438.         lf.lfItalic = TRUE;
  439.     }
  440.     if ( (p = _fstrstr(lpgw->fontname," Bold")) != (LPSTR)NULL ) {
  441.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  442.         lf.lfWeight = FW_BOLD;
  443.     }
  444.  
  445.     if (lpgw->hfonth == 0) {
  446.         lpgw->hfonth = CreateFontIndirect((LOGFONT FAR *)&lf);
  447.     }
  448.  
  449.     if (lpgw->hfontv == 0) {
  450.         lf.lfEscapement = 900;
  451.         lf.lfOrientation = 900;
  452.         lpgw->hfontv = CreateFontIndirect((LOGFONT FAR *)&lf);
  453.     }
  454.  
  455.     /* save text size */
  456.     hfontold = SelectObject(hdc, lpgw->hfonth);
  457. #ifdef WIN32
  458.     {
  459.     SIZE size;
  460.     GetTextExtentPoint(hdc,"0123456789",10, (LPSIZE)&size);
  461.     cx = size.cx;
  462.     cy = size.cy;
  463.     }
  464. #else
  465.     {
  466.     DWORD extent;
  467.     extent = GetTextExtent(hdc,"0123456789",10);
  468.     cx = LOWORD(extent);
  469.     cy = HIWORD(extent);
  470.     }
  471. #endif
  472.     lpgw->vchar = MulDiv(cy,lpgw->ymax,lprect->bottom - lprect->top);
  473.     lpgw->hchar = MulDiv(cx/10,lpgw->xmax,lprect->right - lprect->left);
  474.         /* CMW: Base tick size on character size */
  475.         lpgw->htic = lpgw->hchar/2;
  476.         cy = MulDiv(cx/20, GetDeviceCaps(hdc,LOGPIXELSY), GetDeviceCaps(hdc,LOGPIXELSX));
  477.         lpgw->vtic = MulDiv(cy,lpgw->ymax,lprect->bottom - lprect->top);
  478.     /* find out if we can rotate text 90deg */
  479.     SelectObject(hdc, lpgw->hfontv);
  480.     result = GetDeviceCaps(hdc, TEXTCAPS);
  481.     if ((result & TC_CR_90) || (result & TC_CR_ANY))
  482.         lpgw->rotate = 1;
  483.     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  484.     if (tm.tmPitchAndFamily & TMPF_VECTOR)
  485.         lpgw->rotate = 1;    /* vector fonts can all be rotated */
  486. #if WINVER >=0x030a
  487.     if (tm.tmPitchAndFamily & TMPF_TRUETYPE)
  488.         lpgw->rotate = 1;    /* truetype fonts can all be rotated */
  489. #endif
  490.     SelectObject(hdc, hfontold);
  491.     return;
  492. }
  493.  
  494. void
  495. DestroyFonts(LPGW lpgw)
  496. {
  497.     if (lpgw->hfonth) {
  498.         DeleteObject(lpgw->hfonth);
  499.         lpgw->hfonth = 0;
  500.     }
  501.     if (lpgw->hfontv) {
  502.         DeleteObject(lpgw->hfontv);
  503.         lpgw->hfontv = 0;
  504.     }
  505.     return;
  506. }
  507.  
  508. void
  509. SetFont(LPGW lpgw, HDC hdc)
  510. {
  511.     if (lpgw->rotate && lpgw->angle) {
  512.         if (lpgw->hfontv)
  513.             SelectObject(hdc, lpgw->hfontv);
  514.     }
  515.     else {
  516.         if (lpgw->hfonth)
  517.             SelectObject(hdc, lpgw->hfonth);
  518.     }
  519.     return;
  520. }
  521.  
  522. void
  523. SelFont(LPGW lpgw) {
  524. #if WINVER >= 0x030a
  525.     LOGFONT lf;
  526.     CHOOSEFONT cf;
  527.     HDC hdc;
  528.     char lpszStyle[LF_FACESIZE]; 
  529.     char FAR *p;
  530.  
  531.     /* Set all structure fields to zero. */
  532.     _fmemset(&cf, 0, sizeof(CHOOSEFONT));
  533.     _fmemset(&lf, 0, sizeof(LOGFONT));
  534.     cf.lStructSize = sizeof(CHOOSEFONT);
  535.     cf.hwndOwner = lpgw->hWndGraph;
  536.     _fstrncpy(lf.lfFaceName,lpgw->fontname,LF_FACESIZE);
  537.     if ( (p = _fstrstr(lpgw->fontname," Bold")) != (LPSTR)NULL ) {
  538.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  539.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  540.     }
  541.     else if ( (p = _fstrstr(lpgw->fontname," Italic")) != (LPSTR)NULL ) {
  542.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  543.         lf.lfFaceName[ (unsigned int)(p-lpgw->fontname) ] = '\0';
  544.     }
  545.     else
  546.         _fstrcpy(lpszStyle,"Regular");
  547.     cf.lpszStyle = lpszStyle;
  548.     hdc = GetDC(lpgw->hWndGraph);
  549.     lf.lfHeight = -MulDiv(lpgw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  550.     ReleaseDC(lpgw->hWndGraph, hdc);
  551.     cf.lpLogFont = &lf;
  552.     cf.nFontType = SCREEN_FONTTYPE;
  553.     cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_USESTYLE;
  554.     if (ChooseFont(&cf)) {
  555.         _fstrcpy(lpgw->fontname,lf.lfFaceName);
  556.         lpgw->fontsize = cf.iPointSize / 10;
  557.         if (cf.nFontType & BOLD_FONTTYPE)
  558.             lstrcat(lpgw->fontname," Bold");
  559.         if (cf.nFontType & ITALIC_FONTTYPE)
  560.             lstrcat(lpgw->fontname," Italic");
  561.         SendMessage(lpgw->hWndGraph,WM_COMMAND,M_REBUILDTOOLS,0L);
  562.     }
  563. #endif
  564. }
  565.  
  566. /* ================================== */
  567.  
  568. static void dot(HDC hdc, int xdash, int ydash)
  569. {
  570.     MoveTo(hdc, xdash, ydash);
  571.     LineTo(hdc, xdash, ydash+1);
  572. }
  573.  
  574.  
  575. void
  576. drawgraph(LPGW lpgw, HDC hdc, LPRECT rect)
  577. {
  578.     int xdash, ydash;            /* the transformed coordinates */
  579.     int rr, rl, rt, rb;
  580.     struct GWOP FAR *curptr;
  581.     struct GWOPBLK *blkptr;
  582.     int htic, vtic;
  583.     int hshift, vshift;
  584.     unsigned int lastop=-1;        /* used for plotting last point on a line */
  585.     int pen, numsolid;
  586.     int polymax = 200;
  587.     int polyi = 0;
  588.     POINT *ppt;
  589.     unsigned int ngwop=0;
  590.     BOOL isColor;
  591.  
  592.     if (lpgw->locked) 
  593.         return;
  594.  
  595.      isColor= (GetDeviceCaps(hdc, PLANES)*GetDeviceCaps(hdc,BITSPIXEL)) > 2;
  596.     if (lpgw->background != RGB(255,255,255) && lpgw->color && isColor) {
  597.         SetBkColor(hdc,lpgw->background);
  598.         FillRect(hdc, rect, lpgw->hbrush);
  599.     }
  600.  
  601.     ppt = (POINT *)LocalAllocPtr(LHND, (polymax+1) * sizeof(POINT));
  602.  
  603.     rr = rect->right;
  604.     rl = rect->left;
  605.     rt = rect->top;
  606.     rb = rect->bottom;
  607.  
  608.     htic = lpgw->org_pointsize*MulDiv(lpgw->htic, rr-rl, lpgw->xmax) + 1;
  609.     vtic = lpgw->org_pointsize*MulDiv(lpgw->vtic, rb-rt, lpgw->ymax) + 1;
  610.  
  611.     lpgw->angle = 0;
  612.     SetFont(lpgw, hdc);
  613.     SetTextAlign(hdc, TA_LEFT|TA_BOTTOM);
  614.     vshift = MulDiv(lpgw->vchar, rb-rt, lpgw->ymax)/2;
  615.     /* HBB 980630: new variable for moving rotated text to the correct
  616.      * position: */
  617.     hshift = MulDiv(lpgw->vchar, rr-rl, lpgw->xmax)/2;
  618.  
  619.     pen = 0;
  620.     SelectObject(hdc, lpgw->hpen[pen]);
  621.     SelectObject(hdc, lpgw->colorbrush[pen+2]);
  622.     numsolid = lpgw->numsolid;
  623.  
  624.     /* do the drawing */
  625.     blkptr = lpgw->gwopblk_head;
  626.     curptr = NULL;
  627.     if (blkptr) {
  628.         if (!blkptr->gwop)
  629.             blkptr->gwop = (struct GWOP FAR *)GlobalLock(blkptr->hblk);
  630.         if (!blkptr->gwop)
  631.             return;
  632.         curptr = (struct GWOP FAR *)blkptr->gwop;
  633.     }
  634.     while(ngwop < lpgw->nGWOP)
  635.        {
  636.         /* transform the coordinates */
  637.         xdash = MulDiv(curptr->x, rr-rl-1, lpgw->xmax) + rl;
  638.         ydash = MulDiv(curptr->y, rt-rb+1, lpgw->ymax) + rb - 1;
  639.         if ((lastop==W_vect) && (curptr->op!=W_vect)) {
  640.             if (polyi >= 2)
  641.                 Polyline(hdc, ppt, polyi);
  642.             polyi = 0;
  643.         }
  644.         switch (curptr->op) {
  645.             case 0:    /* have run past last in this block */
  646.                 break;
  647.             case W_move:
  648.                 ppt[0].x = xdash;
  649.                 ppt[0].y = ydash;
  650.                 polyi = 1;
  651.                 break;
  652.             case W_vect:
  653.                 ppt[polyi].x = xdash;
  654.                 ppt[polyi].y = ydash;
  655.                 polyi++;
  656.                 if (polyi >= polymax) {
  657.                     Polyline(hdc, ppt, polyi);
  658.                     ppt[0].x = xdash;
  659.                     ppt[0].y = ydash;
  660.                     polyi = 1;;
  661.                 }
  662.                 break;
  663.             case W_line_type:
  664.                 switch (curptr->x)
  665.                 {
  666.                     case (WORD) -2:        /* black 2 pixel wide */
  667.                         SelectObject(hdc, lpgw->hbpen);
  668.                         if (lpgw->color && isColor)
  669.                             SetTextColor(hdc, lpgw->colorpen[0].lopnColor);
  670.                         break;
  671.                     case (WORD) -1:        /* black 1 pixel wide doted */
  672.                         SelectObject(hdc, lpgw->hapen);
  673.                         if (lpgw->color && isColor)
  674.                             SetTextColor(hdc, lpgw->colorpen[1].lopnColor);
  675.                         break;
  676.                     default:
  677.                         SelectObject(hdc, lpgw->hpen[(curptr->x)%WGNUMPENS]);
  678.                         if (lpgw->color && isColor)
  679.                             SetTextColor(hdc, lpgw->colorpen[(curptr->x)%WGNUMPENS + 2].lopnColor);
  680.                 }
  681.                 pen = curptr->x;
  682.                 SelectObject(hdc, lpgw->colorbrush[pen%WGNUMPENS + 2]);
  683.                 break;
  684.             case W_put_text:
  685.                 {char *str;
  686.                 str = LocalLock(curptr->htext);
  687.                 if (str) {
  688.                     /* HBB 980630: shift differently for rotated text: */
  689.                     if (lpgw->angle)
  690.                         xdash += hshift;
  691.                     else
  692.                     ydash += vshift;
  693.                     SetBkMode(hdc,TRANSPARENT);
  694.                     TextOut(hdc,xdash,ydash,str,lstrlen(str));
  695.                     SetBkMode(hdc,OPAQUE);
  696.                 }
  697.                 LocalUnlock(curptr->htext);
  698.                 }
  699.                 break;
  700.             case W_text_angle:
  701.                 lpgw->angle = curptr->x;
  702.                 SetFont(lpgw,hdc);
  703.                 break;
  704.             case W_justify:
  705.                 switch (curptr->x)
  706.                 {
  707.                     case LEFT:
  708.                         SetTextAlign(hdc, TA_LEFT|TA_BOTTOM);
  709.                         break;
  710.                     case RIGHT:
  711.                         SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);
  712.                         break;
  713.                     case CENTRE:
  714.                         SetTextAlign(hdc, TA_CENTER|TA_BOTTOM);
  715.                         break;
  716.                     }
  717.                 break;
  718.             case W_pointsize:
  719.                 /* HBB 980309: term->pointsize() passes the number as a scaled-up
  720.                  * integer now, so we can avoid calling sscanf() here (in a Win16
  721.                  * DLL sharing stack with the stack-starved wgnuplot.exe !).
  722.                  */
  723.                 if (curptr->x != 0) {
  724.                     double pointsize = curptr->x / 100.0;
  725.                     /* HBB 980309: the older code didn't make *any* use of the
  726.                      * pointsize at all! That obviously can't be correct. So use it! */
  727.                     htic = pointsize*MulDiv(lpgw->htic, rr-rl, lpgw->xmax) + 1;
  728.                     vtic = pointsize*MulDiv(lpgw->vtic, rb-rt, lpgw->ymax) + 1;
  729.                                } else {
  730.                     char *str;
  731.                     str = LocalLock(curptr->htext);
  732.                     if (str) {
  733.                         double pointsize;
  734.                         sscanf(str, "%lg", &pointsize);
  735.                         htic = lpgw->org_pointsize*MulDiv(lpgw->htic, rr-rl, lpgw->xmax) + 1;
  736.                         vtic = lpgw->org_pointsize*MulDiv(lpgw->vtic, rb-rt, lpgw->ymax) + 1;
  737.                     }
  738.                     LocalUnlock(curptr->htext);
  739.                 }
  740.                 break;
  741.             default:    /* A plot mark */
  742. #if 0 /* HBB 980118: fix 'sumsolid' gotcha: */
  743.                 if (pen >= numsolid) {
  744.                     pen %= numsolid;    /* select solid pen */
  745.                     SelectObject(hdc, lpgw->hpen[pen]);
  746.                     SelectObject(hdc, lpgw->colorbrush[pen+2]);
  747.                 }
  748. #else
  749.                                 SelectObject(hdc, lpgw->hsolidpen[pen%WGNUMPENS]);
  750. #endif
  751.                                 switch (curptr->op) {
  752.                     case W_dot:
  753.                         dot(hdc, xdash, ydash);
  754.                         break;
  755.                     case W_plus: /* do plus */ 
  756.                         MoveTo(hdc,xdash-htic,ydash);
  757.                         LineTo(hdc,xdash+htic+1,ydash);
  758.                         MoveTo(hdc,xdash,ydash-vtic);
  759.                         LineTo(hdc,xdash,ydash+vtic+1);
  760.                         break;
  761.                     case W_cross: /* do X */ 
  762.                         MoveTo(hdc,xdash-htic,ydash-vtic);
  763.                         LineTo(hdc,xdash+htic+1,ydash+vtic+1);
  764.                         MoveTo(hdc,xdash-htic,ydash+vtic);
  765.                         LineTo(hdc,xdash+htic+1,ydash-vtic-1);
  766.                         break;
  767.                     case W_star: /* do star */ 
  768.                         MoveTo(hdc,xdash-htic,ydash);
  769.                         LineTo(hdc,xdash+htic+1,ydash);
  770.                         MoveTo(hdc,xdash,ydash-vtic);
  771.                         LineTo(hdc,xdash,ydash+vtic+1);
  772.                         MoveTo(hdc,xdash-htic,ydash-vtic);
  773.                         LineTo(hdc,xdash+htic+1,ydash+vtic+1);
  774.                         MoveTo(hdc,xdash-htic,ydash+vtic);
  775.                         LineTo(hdc,xdash+htic+1,ydash-vtic-1);
  776.                         break;
  777.                     case W_circle: /* do open circle */ 
  778.                         Arc(hdc, xdash-htic, ydash-vtic, xdash+htic+1, ydash+vtic+1, xdash, ydash+vtic+1, xdash, ydash+vtic+1);
  779.                         dot(hdc, xdash, ydash);
  780.                         break;
  781.                     case W_fcircle: /* do filled circle */ 
  782.                             Ellipse(hdc, xdash-htic, ydash-vtic, xdash+htic+1, ydash+vtic+1);
  783.                         break;
  784.                     default:    /* Closed figure */
  785.                           {    POINT p[6];
  786.                             int i;
  787.                         int shape;
  788.                         int filled = 0;
  789.                         static float pointshapes[5][10] = {
  790.                             {-1, -1, +1, -1, +1, +1, -1, +1, 0, 0}, /* box */
  791.                             { 0, +1, -1,  0,  0, -1, +1,  0, 0, 0}, /* diamond */
  792.                             { 0, -4./3, -4./3, 2./3, 4./3,  2./3, 0, 0}, /* triangle */
  793.                             { 0, 4./3, -4./3, -2./3, 4./3,  -2./3, 0, 0}, /* inverted triangle */
  794.                             { 0, 1, 0.95106, 0.30902, 0.58779, -0.80902, -0.58779, -0.80902, -0.95106, 0.30902} /* pentagon (not used) */
  795.                         };
  796.                         switch (curptr->op) {
  797.                             case W_box:         shape = 0;    break;
  798.                             case W_diamond:        shape = 1;    break;
  799.                             case W_itriangle:    shape = 2;    break;
  800.                             case W_triangle:    shape = 3;    break;
  801.                             default:        shape = curptr->op-W_fbox;
  802.                                         filled = 1;
  803.                                         break;
  804.                         }
  805.                         
  806.                             for ( i = 0; i<5; ++i )
  807.                                 if ( pointshapes[shape][i*2+1] == 0 && pointshapes[shape][i*2] == 0 )
  808.                                     break;
  809.                             else {
  810.                                     p[i].x = xdash + htic*pointshapes[shape][i*2] + 0.5;
  811.                                         p[i].y = ydash + vtic*pointshapes[shape][i*2+1] + 0.5;
  812.                                     }
  813.                             if ( filled )
  814.                             /* Filled polygon */
  815.                                     Polygon(hdc, p, i);
  816.                             else {
  817.                                     /* Outline polygon */
  818.                                     p[i].x = p[0].x;
  819.                                     p[i].y = p[0].y;
  820.                                     Polyline(hdc, p, i+1);
  821.                                     dot(hdc, xdash, ydash);
  822.                             }
  823.                           }
  824.                 }
  825.         }
  826.         lastop = curptr->op;
  827.         ngwop++;
  828.         curptr++;
  829.         if ((unsigned)(curptr - blkptr->gwop) >= GWOPMAX) {
  830.             GlobalUnlock(blkptr->hblk);
  831.             blkptr->gwop = (struct GWOP FAR *)NULL;
  832.             blkptr = blkptr->next;
  833.             if (!blkptr->gwop)
  834.                 blkptr->gwop = (struct GWOP FAR *)GlobalLock(blkptr->hblk);
  835.             if (!blkptr->gwop)
  836.                     return;
  837.                 curptr = (struct GWOP FAR *)blkptr->gwop;
  838.         }
  839.     }
  840.     if (polyi >= 2)
  841.         Polyline(hdc, ppt, polyi);
  842.     LocalFreePtr(ppt);
  843. }
  844.  
  845. /* ================================== */
  846.  
  847. /* copy graph window to clipboard */
  848. void
  849. CopyClip(LPGW lpgw)
  850. {
  851.     RECT rect;
  852.     HDC mem;
  853.     HBITMAP bitmap;
  854.     HANDLE hmf;
  855.     GLOBALHANDLE hGMem;
  856.     LPMETAFILEPICT lpMFP;
  857.     HWND hwnd;
  858.     HDC hdc;
  859.  
  860.     hwnd = lpgw->hWndGraph;
  861.  
  862.     /* view the window */
  863.     if (IsIconic(hwnd))
  864.         ShowWindow(hwnd, SW_SHOWNORMAL);
  865.     BringWindowToTop(hwnd);
  866.     UpdateWindow(hwnd);
  867.  
  868.     /* get the context */
  869.     hdc = GetDC(hwnd);
  870.     GetClientRect(hwnd, &rect);
  871.     /* make a bitmap and copy it there */
  872.     mem = CreateCompatibleDC(hdc);
  873.     bitmap = CreateCompatibleBitmap(hdc, rect.right - rect.left,
  874.             rect.bottom - rect.top);
  875.     if (bitmap) {
  876.         /* there is enough memory and the bitmaps OK */
  877.         SelectObject(mem, bitmap);
  878.         BitBlt(mem,0,0,rect.right - rect.left, 
  879.             rect.bottom - rect.top, hdc, rect.left,
  880.             rect.top, SRCCOPY);
  881.     }
  882.     else {
  883.         MessageBeep(MB_ICONHAND);
  884.         MessageBox(hwnd, "Insufficient Memory to Copy Clipboard", 
  885.             lpgw->Title, MB_ICONHAND | MB_OK);
  886.     }
  887.     DeleteDC(mem);
  888.     {
  889.     GW gwclip = *lpgw;
  890.     int windowfontsize = MulDiv(lpgw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  891.     int i;
  892.     gwclip.fontsize = MulDiv(windowfontsize, lpgw->ymax, rect.bottom);
  893.     gwclip.hfonth = gwclip.hfontv = 0;
  894.  
  895.     /* HBB 981203: scale up pens as well... */
  896.     for (i=0; i<WGNUMPENS+2; i++) {
  897.         if(gwclip.monopen[i].lopnWidth.x > 1)
  898.             gwclip.monopen[i].lopnWidth.x =
  899.                 MulDiv(gwclip.monopen[i].lopnWidth.x,
  900.                     gwclip.xmax, rect.right-rect.left);
  901.         if(gwclip.colorpen[i].lopnWidth.x > 1)
  902.             gwclip.colorpen[i].lopnWidth.x =
  903.                 MulDiv(gwclip.colorpen[i].lopnWidth.x,
  904.                     gwclip.xmax, rect.right-rect.left);
  905.     }
  906.  
  907.     rect.right = lpgw->xmax;
  908.     rect.bottom = lpgw->ymax;
  909.     
  910.     MakePens(&gwclip, hdc);
  911.     MakeFonts(&gwclip, &rect, hdc);
  912.  
  913.     ReleaseDC(hwnd, hdc);
  914.  
  915.     hdc = CreateMetaFile((LPSTR)NULL);
  916.  
  917. /* HBB 981203: According to Petzold, Metafiles shouldn't contain SetMapMode() calls: */
  918.     /*SetMapMode(hdc, MM_ANISOTROPIC);*/
  919. #ifdef WIN32
  920.     SetWindowExtEx(hdc, rect.right, rect.bottom, (LPSIZE)NULL);
  921. #else
  922.     SetWindowExt(hdc, rect.right, rect.bottom);
  923. #endif
  924.     drawgraph(&gwclip, hdc, (void *) &rect);
  925.     hmf = CloseMetaFile(hdc);
  926.     DestroyFonts(&gwclip);
  927.     DestroyPens(&gwclip);
  928.     }
  929.  
  930.     hGMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)sizeof(METAFILEPICT));
  931.     lpMFP = (LPMETAFILEPICT) GlobalLock(hGMem);
  932.     hdc = GetDC(hwnd);    /* get window size */
  933.     GetClientRect(hwnd, &rect);
  934.     /* in MM_ANISOTROPIC, xExt & yExt give suggested size in 0.01mm units */
  935.     lpMFP->mm = MM_ANISOTROPIC;
  936.     lpMFP->xExt = MulDiv(rect.right-rect.left, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
  937.     /* HBB 981203: Seems it should be LOGPIXELS_Y_, here, not _X_*/
  938.     lpMFP->yExt = MulDiv(rect.bottom-rect.top, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
  939.     lpMFP->hMF = hmf;
  940.     ReleaseDC(hwnd, hdc);
  941.     GlobalUnlock(hGMem);
  942.  
  943.     OpenClipboard(hwnd);
  944.     EmptyClipboard();
  945.     SetClipboardData(CF_METAFILEPICT,hGMem);
  946.     SetClipboardData(CF_BITMAP, bitmap);
  947.     CloseClipboard();
  948.     return;
  949. }
  950.  
  951. /* copy graph window to printer */
  952. void
  953. CopyPrint(LPGW lpgw)
  954. {
  955. #ifdef WIN32
  956.     DOCINFO docInfo;
  957. #endif
  958.  
  959. #if WINVER >= 0x030a
  960.     HDC printer;
  961.     DLGPROC lpfnAbortProc;
  962.     DLGPROC lpfnPrintDlgProc;
  963.     PRINTDLG pd;
  964.     HWND hwnd;
  965.     RECT rect;
  966.     PRINT pr;
  967.     UINT widabort;
  968.  
  969.     hwnd = lpgw->hWndGraph;
  970.  
  971.     _fmemset(&pd, 0, sizeof(PRINTDLG));
  972.     pd.lStructSize = sizeof(PRINTDLG);
  973.     pd.hwndOwner = hwnd;
  974.     pd.Flags = PD_PRINTSETUP | PD_RETURNDC;
  975.  
  976.     if (!PrintDlg(&pd))
  977.         return;
  978.     printer = pd.hDC;
  979.     if (NULL == printer)
  980.         return;    /* abort */
  981.  
  982.     if (!PrintSize(printer, hwnd, &rect)) {
  983.         DeleteDC(printer);
  984.         return; /* abort */
  985.     }
  986.  
  987.     pr.hdcPrn = printer;
  988.     SetWindowLong(hwnd, 4, (LONG)((LPPRINT)&pr));
  989. #ifdef WIN32
  990.     PrintRegister((LPPRINT)&pr);
  991. #endif
  992.  
  993.     EnableWindow(hwnd,FALSE);
  994.     pr.bUserAbort = FALSE;
  995. #ifdef WIN32
  996.     pr.hDlgPrint = CreateDialogParam(hdllInstance,"CancelDlgBox",hwnd,PrintDlgProc,(LPARAM)lpgw->Title);
  997.     SetAbortProc(printer,PrintAbortProc);  
  998.  
  999.     memset(&docInfo, 0, sizeof(DOCINFO));
  1000.     docInfo.cbSize = sizeof(DOCINFO);
  1001.     docInfo.lpszDocName = lpgw->Title;
  1002.  
  1003.     if (StartDoc(printer, &docInfo) > 0) {
  1004. #else
  1005. #ifdef __DLL__
  1006.     lpfnPrintDlgProc = (DLGPROC)GetProcAddress(hdllInstance, "PrintDlgProc");
  1007.     lpfnAbortProc = (DLGPROC)GetProcAddress(hdllInstance, "PrintAbortProc");
  1008. #else
  1009.     lpfnPrintDlgProc = (DLGPROC)MakeProcInstance((FARPROC)PrintDlgProc, hdllInstance);
  1010.     lpfnAbortProc = (DLGPROC)MakeProcInstance((FARPROC)PrintAbortProc, hdllInstance);
  1011. #endif
  1012.     pr.hDlgPrint = CreateDialogParam(hdllInstance,"CancelDlgBox",hwnd,lpfnPrintDlgProc,(LPARAM)lpgw->Title);
  1013.     Escape(printer,SETABORTPROC,0,(LPSTR)lpfnAbortProc,NULL);  
  1014.     if (Escape(printer, STARTDOC, lstrlen(lpgw->Title),lpgw->Title, NULL) > 0) {
  1015. #endif
  1016.         SetMapMode(printer, MM_TEXT);
  1017.         SetBkMode(printer,OPAQUE);
  1018. #ifdef WIN32
  1019.         StartPage(printer);
  1020. #endif
  1021.         DestroyFonts(lpgw);
  1022.         MakeFonts(lpgw, (RECT FAR *)&rect, printer);
  1023.         DestroyPens(lpgw);    /* rebuild pens */
  1024.         MakePens(lpgw, printer);
  1025.         drawgraph(lpgw, printer, (void *) &rect);
  1026. #ifdef WIN32
  1027.         if (EndPage(printer) > 0)
  1028.             EndDoc(printer);
  1029. #else
  1030.         if (Escape(printer,NEWFRAME,0,NULL,NULL) > 0)
  1031.             Escape(printer,ENDDOC,0,NULL,NULL);
  1032. #endif
  1033.     }
  1034.     if (!pr.bUserAbort) {
  1035.         EnableWindow(hwnd,TRUE);
  1036.         DestroyWindow(pr.hDlgPrint);
  1037.     }
  1038. #ifndef WIN32
  1039. #ifndef __DLL__
  1040.     FreeProcInstance((FARPROC)lpfnPrintDlgProc);
  1041.     FreeProcInstance((FARPROC)lpfnAbortProc);
  1042. #endif
  1043. #endif
  1044.     DeleteDC(printer);
  1045.     SetWindowLong(hwnd, 4, (LONG)(0L));
  1046. #ifdef WIN32
  1047.     PrintUnregister((LPPRINT)&pr);
  1048. #endif
  1049.     /* make certain that the screen pen set is restored */
  1050.     SendMessage(lpgw->hWndGraph,WM_COMMAND,M_REBUILDTOOLS,0L);
  1051. #endif
  1052.     return;
  1053. }
  1054.  
  1055. /* ================================== */
  1056. /*  INI file stuff */
  1057. void
  1058. WriteGraphIni(LPGW lpgw)
  1059. {
  1060.     RECT rect;
  1061.     int i;
  1062.     char entry[32];
  1063.     LPLOGPEN pc;
  1064.     LPLOGPEN pm;
  1065.     LPSTR file = lpgw->IniFile;
  1066.     LPSTR section = lpgw->IniSection;
  1067.     char profile[80];
  1068.  
  1069.     if ((file == (LPSTR)NULL) || (section == (LPSTR)NULL))
  1070.         return;
  1071.     if (IsIconic(lpgw->hWndGraph))
  1072.         ShowWindow(lpgw->hWndGraph, SW_SHOWNORMAL);
  1073.     GetWindowRect(lpgw->hWndGraph,&rect);
  1074.     wsprintf(profile, "%d %d", rect.left, rect.top);
  1075.     WritePrivateProfileString(section, "GraphOrigin", profile, file);
  1076.     wsprintf(profile, "%d %d", rect.right-rect.left, rect.bottom-rect.top);
  1077.     WritePrivateProfileString(section, "GraphSize", profile, file);
  1078.     wsprintf(profile, "%s,%d", lpgw->fontname, lpgw->fontsize);
  1079.     WritePrivateProfileString(section, "GraphFont", profile, file);
  1080.     wsprintf(profile, "%d", lpgw->color);
  1081.     WritePrivateProfileString(section, "GraphColor", profile, file);
  1082.     wsprintf(profile, "%d", lpgw->graphtotop);
  1083.     WritePrivateProfileString(section, "GraphToTop", profile, file);
  1084.     wsprintf(profile, "%d %d %d",GetRValue(lpgw->background),
  1085.             GetGValue(lpgw->background), GetBValue(lpgw->background));
  1086.     WritePrivateProfileString(section, "GraphBackground", profile, file);
  1087.  
  1088.     /* now save pens */
  1089.     for (i=0; i<WGNUMPENS+2; i++) {
  1090.         if (i==0)
  1091.             _fstrcpy(entry,"Border");
  1092.         else if (i==1)
  1093.             _fstrcpy(entry,"Axis");
  1094.         else
  1095.              wsprintf(entry,"Line%d",i-1);
  1096.         pc = &lpgw->colorpen[i];
  1097.         pm = &lpgw->monopen[i];
  1098.         wsprintf(profile, "%d %d %d %d %d",GetRValue(pc->lopnColor),
  1099.             GetGValue(pc->lopnColor), GetBValue(pc->lopnColor),
  1100.             (pc->lopnWidth.x != 1) ? -pc->lopnWidth.x : pc->lopnStyle, 
  1101.             (pm->lopnWidth.x != 1) ? -pm->lopnWidth.x : pm->lopnStyle);
  1102.         WritePrivateProfileString(section, entry, profile, file);
  1103.     }
  1104.     return;
  1105. }
  1106.  
  1107. void
  1108. ReadGraphIni(LPGW lpgw)
  1109. {
  1110.     LPSTR file = lpgw->IniFile;
  1111.     LPSTR section = lpgw->IniSection;
  1112.     char profile[81];
  1113.     char entry[32];
  1114.     LPSTR p;
  1115.     int i,r,g,b,colorstyle,monostyle;
  1116.     COLORREF ref;
  1117.     BOOL bOKINI;
  1118.  
  1119.     bOKINI = (file != (LPSTR)NULL) && (section != (LPSTR)NULL);
  1120.     if (!bOKINI)
  1121.         profile[0] = '\0';
  1122.  
  1123.     if (bOKINI)
  1124.       GetPrivateProfileString(section, "GraphOrigin", "", profile, 80, file);
  1125.     if ( (p = GetInt(profile, (LPINT)&lpgw->Origin.x)) == NULL)
  1126.         lpgw->Origin.x = CW_USEDEFAULT;
  1127.     if ( (p = GetInt(p, (LPINT)&lpgw->Origin.y)) == NULL)
  1128.         lpgw->Origin.y = CW_USEDEFAULT;
  1129.     if (bOKINI)
  1130.       GetPrivateProfileString(section, "GraphSize", "", profile, 80, file);
  1131.     if ( (p = GetInt(profile, (LPINT)&lpgw->Size.x)) == NULL)
  1132.         lpgw->Size.x = CW_USEDEFAULT;
  1133.     if ( (p = GetInt(p, (LPINT)&lpgw->Size.y)) == NULL)
  1134.         lpgw->Size.y = CW_USEDEFAULT;
  1135.  
  1136.     if (bOKINI)
  1137.       GetPrivateProfileString(section, "GraphFont", "", profile, 80, file);
  1138.     {
  1139.         char FAR *size;
  1140.         size = _fstrchr(profile,',');
  1141.         if (size) {
  1142.             *size++ = '\0';
  1143.             if ( (p = GetInt(size, (LPINT)&lpgw->fontsize)) == NULL)
  1144.                 lpgw->fontsize = WINFONTSIZE;
  1145.         }
  1146.         _fstrcpy(lpgw->fontname, profile);
  1147.         if (lpgw->fontsize == 0)
  1148.             lpgw->fontsize = WINFONTSIZE;
  1149.         if (!(*lpgw->fontname))
  1150.             if (LOWORD(GetVersion()) == 3)
  1151.                 _fstrcpy(lpgw->fontname,WIN30FONT);
  1152.             else
  1153.                 _fstrcpy(lpgw->fontname,WINFONT);
  1154.     }
  1155.  
  1156.     if (bOKINI)
  1157.       GetPrivateProfileString(section, "GraphColor", "", profile, 80, file);
  1158.         if ( (p = GetInt(profile, (LPINT)&lpgw->color)) == NULL)
  1159.             lpgw->color = TRUE;
  1160.  
  1161.     if (bOKINI)
  1162.       GetPrivateProfileString(section, "GraphToTop", "", profile, 80, file);
  1163.         if ( (p = GetInt(profile, (LPINT)&lpgw->graphtotop)) == NULL)
  1164.             lpgw->graphtotop = TRUE;
  1165.  
  1166.     lpgw->background = RGB(255,255,255);
  1167.     if (bOKINI)
  1168.       GetPrivateProfileString(section, "GraphBackground", "", profile, 80, file);
  1169.     if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1170.          ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1171.          ((p = GetInt(p, (LPINT)&b)) != NULL) )
  1172.             lpgw->background = RGB(r,g,b);
  1173.  
  1174.     StorePen(lpgw, 0,RGB(0,0,0),рр…Ñ€рD);
  1175.     if (bOKINI)
  1176.       GetPrivateProfileString(section, "Border", "", profile, 80, file);
  1177.     if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1178.          ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1179.          ((p = GetInt(p, (LPINT)&b)) != NULL) &&
  1180.          ((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
  1181.          ((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
  1182.             StorePen(lpgw,0,RGB(r,g,b),colorstyle,monostyle);
  1183.  
  1184.     StorePen(lpgw, 1,RGB(192,192,192),PS_DOT,PS_DOT);
  1185.     if (bOKINI)
  1186.       GetPrivateProfileString(section, "Axis", "", profile, 80, file);
  1187.     if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1188.          ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1189.          ((p = GetInt(p, (LPINT)&b)) != NULL) &&
  1190.          ((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
  1191.          ((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
  1192.             StorePen(lpgw,1,RGB(r,g,b),colorstyle,monostyle);
  1193.  
  1194.     for (i=0; i<WGNUMPENS; i++)
  1195.     {
  1196.         ref = wginitcolor[ i%WGDEFCOLOR ];
  1197.         colorstyle = wginitstyle[ (i/WGDEFCOLOR) % WGDEFSTYLE ];
  1198.         monostyle  = wginitstyle[ i%WGDEFSTYLE ];
  1199.         StorePen(lpgw, i+2,ref,colorstyle,monostyle);
  1200.         wsprintf(entry,"Line%d",i+1);
  1201.         if (bOKINI)
  1202.           GetPrivateProfileString(section, entry, "", profile, 80, file);
  1203.         if ( ((p = GetInt(profile, (LPINT)&r)) != NULL) &&
  1204.              ((p = GetInt(p, (LPINT)&g)) != NULL) &&
  1205.              ((p = GetInt(p, (LPINT)&b)) != NULL) &&
  1206.              ((p = GetInt(p, (LPINT)&colorstyle)) != NULL) &&
  1207.              ((p = GetInt(p, (LPINT)&monostyle)) != NULL) )
  1208.                 StorePen(lpgw,i+2,RGB(r,g,b),colorstyle,monostyle);
  1209.     }
  1210. }
  1211.  
  1212.  
  1213. /* ================================== */
  1214.  
  1215. #define LS_DEFLINE 2
  1216. typedef struct tagLS {
  1217.     int    widtype;
  1218.     int    wid;
  1219.     HWND    hwnd;
  1220.     int    pen;            /* current pen number */
  1221.     LOGPEN    colorpen[WGNUMPENS+2];    /* logical color pens */
  1222.     LOGPEN    monopen[WGNUMPENS+2];    /* logical mono pens */
  1223. } LS;
  1224. typedef LS FAR*  LPLS;
  1225.     
  1226.  
  1227. COLORREF
  1228. GetColor(HWND hwnd, COLORREF ref)
  1229. {
  1230. CHOOSECOLOR cc;
  1231. COLORREF aclrCust[16];
  1232. int i;
  1233.  
  1234.     for (i=0; i<16; i++) {
  1235.         aclrCust[i] = RGB(0,0,0);
  1236.     }
  1237.     _fmemset(&cc, 0, sizeof(CHOOSECOLOR));
  1238.     cc.lStructSize = sizeof(CHOOSECOLOR);
  1239.     cc.hwndOwner = hwnd;
  1240.     cc.lpCustColors = aclrCust;
  1241.     cc.rgbResult = ref;
  1242.     cc.Flags = CC_RGBINIT;
  1243.     if (ChooseColor(&cc))
  1244.         return cc.rgbResult;
  1245.     return ref;
  1246. }
  1247.  
  1248.  
  1249. /* force update of owner draw button */
  1250. void
  1251. UpdateColorSample(HWND hdlg)
  1252. {
  1253.     RECT rect;
  1254.     POINT ptul, ptlr;
  1255.     GetWindowRect( GetDlgItem(hdlg, LS_COLORSAMPLE), &rect);
  1256.     ptul.x = rect.left;
  1257.     ptul.y = rect.top;
  1258.     ptlr.x = rect.right;
  1259.     ptlr.y = rect.bottom;
  1260.     ScreenToClient(hdlg, &ptul);
  1261.     ScreenToClient(hdlg, &ptlr);
  1262.     rect.left   = ptul.x;
  1263.     rect.top    = ptul.y;
  1264.     rect.right  = ptlr.x;
  1265.     rect.bottom = ptlr.y;
  1266.     InvalidateRect(hdlg, &rect, TRUE);
  1267.     UpdateWindow(hdlg);
  1268. }
  1269.  
  1270. BOOL CALLBACK WINEXPORT
  1271. LineStyleDlgProc(HWND hdlg, UINT wmsg, WPARAM wparam, LPARAM lparam)
  1272. {
  1273.     char buf[16];
  1274.     LPLS lpls;
  1275.     int i;
  1276.     UINT pen;
  1277.     LPLOGPEN plpm, plpc;
  1278.     lpls = (LPLS)GetWindowLong(GetParent(hdlg), 4);
  1279.  
  1280.     switch (wmsg) {
  1281.         case WM_INITDIALOG:
  1282.             pen = 2;
  1283.             for (i=0; i<WGNUMPENS+2; i++) {
  1284.                 if (i==0)
  1285.                     _fstrcpy(buf,"Border");
  1286.                 else if (i==1)
  1287.                     _fstrcpy(buf,"Axis");
  1288.                 else
  1289.                      wsprintf(buf,"Line%d",i-1);
  1290.                 SendDlgItemMessage(hdlg, LS_LINENUM, LB_ADDSTRING, 0, 
  1291.                     (LPARAM)((LPSTR)buf));
  1292.             }
  1293.             SendDlgItemMessage(hdlg, LS_LINENUM, LB_SETCURSEL, pen, 0L);
  1294.  
  1295.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1296.                 (LPARAM)((LPSTR)"Solid"));
  1297.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1298.                 (LPARAM)((LPSTR)"Dash"));
  1299.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1300.                 (LPARAM)((LPSTR)"Dot"));
  1301.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1302.                 (LPARAM)((LPSTR)"DashDot"));
  1303.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_ADDSTRING, 0, 
  1304.                 (LPARAM)((LPSTR)"DashDotDot"));
  1305.  
  1306.             plpm = &lpls->monopen[pen];
  1307.             SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1308.                 plpm->lopnStyle, 0L);
  1309.             wsprintf(buf,"%d",plpm->lopnWidth.x);
  1310.             SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1311.  
  1312.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1313.                 (LPARAM)((LPSTR)"Solid"));
  1314.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1315.                 (LPARAM)((LPSTR)"Dash"));
  1316.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1317.                 (LPARAM)((LPSTR)"Dot"));
  1318.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1319.                 (LPARAM)((LPSTR)"DashDot"));
  1320.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_ADDSTRING, 0, 
  1321.                 (LPARAM)((LPSTR)"DashDotDot"));
  1322.  
  1323.             plpc = &lpls->colorpen[pen];
  1324.             SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1325.                 plpc->lopnStyle, 0L);
  1326.             wsprintf(buf,"%d",plpc->lopnWidth.x);
  1327.             SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1328.  
  1329.             return TRUE;
  1330.         case WM_COMMAND:
  1331.             pen = (UINT)SendDlgItemMessage(hdlg, LS_LINENUM, LB_GETCURSEL, 0, 0L);
  1332.             plpm = &lpls->monopen[pen];
  1333.             plpc = &lpls->colorpen[pen];
  1334.             switch (LOWORD(wparam)) {
  1335.                 case LS_LINENUM:
  1336.                     wsprintf(buf,"%d",plpm->lopnWidth.x);
  1337.                     SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1338.                     SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1339.                         plpm->lopnStyle, 0L);
  1340.                     wsprintf(buf,"%d",plpc->lopnWidth.x);
  1341.                     SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1342.                     SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1343.                         plpc->lopnStyle, 0L);
  1344.                     UpdateColorSample(hdlg);
  1345.                     return FALSE;
  1346.                 case LS_MONOSTYLE:
  1347.                     plpm->lopnStyle = 
  1348.                         (UINT)SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_GETCURSEL, 0, 0L);
  1349.                     if (plpm->lopnStyle != 0) {
  1350.                         plpm->lopnWidth.x = 1;
  1351.                         wsprintf(buf,"%d",plpm->lopnWidth.x);
  1352.                         SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1353.                     }
  1354.                     return FALSE;
  1355.                 case LS_MONOWIDTH:
  1356.                     GetDlgItemText(hdlg, LS_MONOWIDTH, buf, 15);
  1357.                     GetInt(buf, (LPINT)&plpm->lopnWidth.x);
  1358.                     if (plpm->lopnWidth.x != 1) {
  1359.                         plpm->lopnStyle = 0;
  1360.                         SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1361.                             plpm->lopnStyle, 0L);
  1362.                     }
  1363.                     return FALSE;
  1364.                 case LS_CHOOSECOLOR:
  1365.                     plpc->lopnColor = GetColor(hdlg, plpc->lopnColor);
  1366.                     UpdateColorSample(hdlg);
  1367.                     return FALSE;
  1368.                 case LS_COLORSTYLE:
  1369.                     plpc->lopnStyle = 
  1370.                         (UINT)SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_GETCURSEL, 0, 0L);
  1371.                     if (plpc->lopnStyle != 0) {
  1372.                         plpc->lopnWidth.x = 1;
  1373.                         wsprintf(buf,"%d",plpc->lopnWidth.x);
  1374.                         SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1375.                     }
  1376.                     return FALSE;
  1377.                 case LS_COLORWIDTH:
  1378.                     GetDlgItemText(hdlg, LS_COLORWIDTH, buf, 15);
  1379.                     GetInt(buf, (LPINT)&plpc->lopnWidth.x);
  1380.                     if (plpc->lopnWidth.x != 1) {
  1381.                         plpc->lopnStyle = 0;
  1382.                         SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1383.                             plpc->lopnStyle, 0L);
  1384.                     }
  1385.                     return FALSE;
  1386.                 case LS_DEFAULT:
  1387.                     plpm = lpls->monopen;
  1388.                     plpc = lpls->colorpen;
  1389.                     /* border */
  1390.                     plpc->lopnColor   = RGB(0,0,0);
  1391.                     plpc->lopnStyle   = PS_SOLID;
  1392.                     plpc->lopnWidth.x = 1;
  1393.                     plpm->lopnStyle   = PS_SOLID;
  1394.                     plpm->lopnWidth.x = 1;
  1395.                     plpc++; plpm++;
  1396.                     /* axis */
  1397.                     plpc->lopnColor   = RGB(192,192,192);
  1398.                     plpc->lopnStyle   = PS_DOT;
  1399.                     plpc->lopnWidth.x = 1;
  1400.                     plpm->lopnStyle   = PS_DOT;
  1401.                     plpm->lopnWidth.x = 1;
  1402.                     /* LineX */
  1403.                     for (i=0; i<WGNUMPENS; i++) {
  1404.                         plpc++; plpm++;
  1405.                         plpc->lopnColor   = wginitcolor[ i%WGDEFCOLOR ];
  1406.                         plpc->lopnStyle   = wginitstyle[ (i/WGDEFCOLOR) % WGDEFSTYLE ];
  1407.                         plpc->lopnWidth.x = 1;
  1408.                         plpm->lopnStyle   = wginitstyle[ i%WGDEFSTYLE ];
  1409.                         plpm->lopnWidth.x = 1;
  1410.                     }
  1411.                     /* update window */
  1412.                     plpm = &lpls->monopen[pen];
  1413.                     plpc = &lpls->colorpen[pen];
  1414.                     SendDlgItemMessage(hdlg, LS_LINENUM, LB_SETCURSEL, pen, 0L);
  1415.                     wsprintf(buf,"%d",plpm->lopnWidth.x);
  1416.                     SetDlgItemText(hdlg, LS_MONOWIDTH, buf);
  1417.                     SendDlgItemMessage(hdlg, LS_MONOSTYLE, CB_SETCURSEL, 
  1418.                         plpm->lopnStyle, 0L);
  1419.                     wsprintf(buf,"%d",plpc->lopnWidth.x);
  1420.                     SetDlgItemText(hdlg, LS_COLORWIDTH, buf);
  1421.                     SendDlgItemMessage(hdlg, LS_COLORSTYLE, CB_SETCURSEL, 
  1422.                         plpc->lopnStyle, 0L);
  1423.                     UpdateColorSample(hdlg);
  1424.                     return FALSE;
  1425.                 case IDOK:
  1426.                     EndDialog(hdlg, IDOK);
  1427.                     return TRUE;
  1428.                 case IDCANCEL:
  1429.                     EndDialog(hdlg, IDCANCEL);
  1430.                     return TRUE;
  1431.             }
  1432.             break;
  1433.         case WM_DRAWITEM:
  1434.             {
  1435.             HBRUSH hBrush;
  1436.             LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lparam;
  1437.             pen = (UINT)SendDlgItemMessage(hdlg, LS_LINENUM, LB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  1438.             plpc = &lpls->colorpen[pen];
  1439.             hBrush = CreateSolidBrush(plpc->lopnColor);
  1440.             FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
  1441.             FrameRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)GetStockObject(BLACK_BRUSH));
  1442.             DeleteObject(hBrush);
  1443.             }
  1444.             return FALSE;
  1445.     }
  1446.     return FALSE;
  1447. }
  1448.  
  1449.  
  1450.  
  1451. /* GetWindowLong(hwnd, 4) must be available for use */
  1452. BOOL
  1453. LineStyle(LPGW lpgw)
  1454. {
  1455. DLGPROC lpfnLineStyleDlgProc ;
  1456. BOOL status = FALSE;
  1457. LS ls;
  1458.     
  1459.     SetWindowLong(lpgw->hWndGraph, 4, (LONG)((LPLS)&ls));
  1460.     _fmemcpy(&ls.colorpen, &lpgw->colorpen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1461.     _fmemcpy(&ls.monopen, &lpgw->monopen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1462.  
  1463. #ifdef WIN32
  1464.     if (DialogBox (hdllInstance, "LineStyleDlgBox", lpgw->hWndGraph, LineStyleDlgProc)
  1465. #else
  1466. #ifdef __DLL__
  1467.     lpfnLineStyleDlgProc = (DLGPROC)GetProcAddress(hdllInstance, "LineStyleDlgProc");
  1468. #else
  1469.     lpfnLineStyleDlgProc = (DLGPROC)MakeProcInstance((FARPROC)LineStyleDlgProc, hdllInstance);
  1470. #endif
  1471.     if (DialogBox (hdllInstance, "LineStyleDlgBox", lpgw->hWndGraph, lpfnLineStyleDlgProc)
  1472. #endif
  1473.         == IDOK) {
  1474.         _fmemcpy(&lpgw->colorpen, &ls.colorpen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1475.         _fmemcpy(&lpgw->monopen, &ls.monopen, (WGNUMPENS + 2) * sizeof(LOGPEN));
  1476.         status = TRUE;
  1477.     }
  1478. #ifndef WIN32
  1479. #ifndef __DLL__
  1480.     FreeProcInstance((FARPROC)lpfnLineStyleDlgProc);
  1481. #endif
  1482. #endif
  1483.     SetWindowLong(lpgw->hWndGraph, 4, (LONG)(0L));
  1484.     return status;
  1485. }
  1486.  
  1487. /* ================================== */
  1488.  
  1489. LRESULT CALLBACK WINEXPORT
  1490. WndGraphProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1491. {
  1492.     HDC hdc;
  1493.     PAINTSTRUCT ps;
  1494.     RECT rect;
  1495.     LPGW lpgw;
  1496.     HMENU sysmenu;
  1497.     int i;
  1498.  
  1499.     lpgw = (LPGW)GetWindowLong(hwnd, 0);
  1500.  
  1501.     switch(message)
  1502.     {
  1503.         case WM_SYSCOMMAND:
  1504.             switch(LOWORD(wParam))
  1505.             {
  1506.                 case M_GRAPH_TO_TOP:
  1507.                 case M_COLOR:
  1508.                 case M_CHOOSE_FONT:
  1509.                 case M_COPY_CLIP:
  1510.                 case M_LINESTYLE:
  1511.                 case M_BACKGROUND:
  1512.                 case M_PRINT:
  1513.                 case M_WRITEINI:
  1514.                 case M_REBUILDTOOLS:
  1515.                     SendMessage(hwnd, WM_COMMAND, wParam, lParam);
  1516.                     break;
  1517.                 case M_ABOUT:
  1518.                     if (lpgw->lptw)
  1519.                         AboutBox(hwnd,lpgw->lptw->AboutText);
  1520.                     return 0;
  1521.                 case M_COMMANDLINE:
  1522.                     sysmenu = GetSystemMenu(lpgw->hWndGraph,0);
  1523.                     i = GetMenuItemCount (sysmenu);
  1524.                     DeleteMenu (sysmenu, --i, MF_BYPOSITION);
  1525.                     DeleteMenu (sysmenu, --i, MF_BYPOSITION);
  1526.                     ShowWindow (lpgw->lptw->hWndParent, SW_SHOW);
  1527.                     break;
  1528.             }
  1529.             break;
  1530.         case WM_COMMAND:
  1531.             switch(LOWORD(wParam))
  1532.             {
  1533.                 case M_GRAPH_TO_TOP:
  1534.                     lpgw->graphtotop = !lpgw->graphtotop;
  1535.                     SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1536.                     return(0);
  1537.                 case M_COLOR:
  1538.                     lpgw->color = !lpgw->color;
  1539.                     SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1540.                     return(0);
  1541.                 case M_CHOOSE_FONT:
  1542.                     SelFont(lpgw);
  1543.                     return 0;
  1544.                 case M_COPY_CLIP:
  1545.                     CopyClip(lpgw);
  1546.                     return 0;
  1547.                 case M_LINESTYLE:
  1548.                     if (LineStyle(lpgw))
  1549.                         SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1550.                     return 0;
  1551.                 case M_BACKGROUND:
  1552.                     lpgw->background = GetColor(hwnd, lpgw->background);
  1553.                     SendMessage(hwnd,WM_COMMAND,M_REBUILDTOOLS,0L);
  1554.                     return 0;
  1555.                 case M_PRINT:
  1556.                     CopyPrint(lpgw);
  1557.                     return 0;
  1558.                 case M_WRITEINI:
  1559.                     WriteGraphIni(lpgw);
  1560.                     if (lpgw->lptw)
  1561.                         WriteTextIni(lpgw->lptw);
  1562.                     return 0;
  1563.                 case M_REBUILDTOOLS:
  1564.                     lpgw->resized = TRUE;
  1565.                     if (lpgw->color) 
  1566.                         CheckMenuItem(lpgw->hPopMenu, M_COLOR, MF_BYCOMMAND | MF_CHECKED);
  1567.                     else
  1568.                         CheckMenuItem(lpgw->hPopMenu, M_COLOR, MF_BYCOMMAND | MF_UNCHECKED);
  1569.                     if (lpgw->graphtotop) 
  1570.                         CheckMenuItem(lpgw->hPopMenu, M_GRAPH_TO_TOP, MF_BYCOMMAND | MF_CHECKED);
  1571.                     else
  1572.                         CheckMenuItem(lpgw->hPopMenu, M_GRAPH_TO_TOP, MF_BYCOMMAND | MF_UNCHECKED);
  1573.                     DestroyPens(lpgw);
  1574.                     DestroyFonts(lpgw);
  1575.                     hdc = GetDC(hwnd);
  1576.                     MakePens(lpgw, hdc);
  1577.                     GetClientRect(hwnd, &rect);
  1578.                     MakeFonts(lpgw, (LPRECT)&rect, hdc);
  1579.                     ReleaseDC(hwnd, hdc);
  1580.                     GetClientRect(hwnd, &rect);
  1581.                     InvalidateRect(hwnd, (LPRECT) &rect, 1);
  1582.                     UpdateWindow(hwnd);
  1583.                     return 0;
  1584.             }
  1585.             return 0;
  1586.         case WM_RBUTTONDOWN:
  1587.             {
  1588.             POINT pt;
  1589.             pt.x = LOWORD(lParam);
  1590.             pt.y = HIWORD(lParam);
  1591.             ClientToScreen(hwnd,&pt);
  1592.             TrackPopupMenu(lpgw->hPopMenu, TPM_LEFTALIGN, 
  1593.                 pt.x, pt.y, 0, hwnd, NULL);
  1594.             }
  1595.             return(0);
  1596.         case WM_CREATE:
  1597.             lpgw = ((CREATESTRUCT FAR *)lParam)->lpCreateParams;
  1598.             SetWindowLong(hwnd, 0, (LONG)lpgw);
  1599.             lpgw->hWndGraph = hwnd;
  1600.             hdc = GetDC(hwnd);
  1601.             MakePens(lpgw, hdc);
  1602.             GetClientRect(hwnd, &rect);
  1603.             MakeFonts(lpgw, (LPRECT)&rect, hdc);
  1604.             ReleaseDC(hwnd, hdc);
  1605. #if WINVER >= 0x030a
  1606.             {
  1607.             WORD version = LOWORD(GetVersion());
  1608.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1609.                 if ( lpgw->lptw && (lpgw->lptw->DragPre!=(LPSTR)NULL) && (lpgw->lptw->DragPost!=(LPSTR)NULL) )
  1610.                     DragAcceptFiles(hwnd, TRUE);
  1611.             }
  1612. #endif
  1613.             return(0);
  1614.         case WM_PAINT:
  1615.             hdc = BeginPaint(hwnd, &ps);
  1616.             SetMapMode(hdc, MM_TEXT);
  1617.             SetBkMode(hdc,OPAQUE);
  1618.             GetClientRect(hwnd, &rect);
  1619. #ifdef WIN32
  1620.             SetViewportExtEx(hdc, rect.right, rect.bottom, NULL);
  1621. #else
  1622.             SetViewportExt(hdc, rect.right, rect.bottom);
  1623. #endif
  1624.             drawgraph(lpgw, hdc, (void *) &rect);
  1625.             EndPaint(hwnd, &ps);
  1626.             return 0;
  1627.         case WM_SIZE:
  1628.             /* update font sizes if graph resized */
  1629.             if ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED)) {
  1630.                 RECT rect;
  1631.                 SendMessage(hwnd,WM_SYSCOMMAND,M_REBUILDTOOLS,0L);
  1632.                 GetWindowRect(hwnd,&rect);
  1633.                 lpgw->Size.x = rect.right-rect.left;
  1634.                 lpgw->Size.y = rect.bottom-rect.top;
  1635.             }
  1636.             break;
  1637. #if WINVER >= 0x030a
  1638.         case WM_DROPFILES:
  1639.             {
  1640.             WORD version = LOWORD(GetVersion());
  1641.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1642.                 if (lpgw->lptw)
  1643.                     DragFunc(lpgw->lptw, (HDROP)wParam);
  1644.             }
  1645.             break;
  1646. #endif
  1647.         case WM_DESTROY:
  1648.             DestroyPens(lpgw);
  1649.             DestroyFonts(lpgw);
  1650. #if __TURBOC__ >= 0x410    /* Borland C++ 3.1 or later */
  1651.             {
  1652.             WORD version = LOWORD(GetVersion());
  1653.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1654.                 DragAcceptFiles(hwnd, FALSE);
  1655.             }
  1656. #endif
  1657.             if (lpgw->lptw && !IsWindowVisible(lpgw->lptw->hWndParent)) {
  1658.                 PostMessage (lpgw->lptw->hWndParent, WM_CLOSE, 0, 0);
  1659.             }
  1660.             return 0;
  1661.         case WM_CLOSE:
  1662.             GraphClose(lpgw);
  1663.             return 0;
  1664.         }
  1665.     return DefWindowProc(hwnd, message, wParam, lParam);
  1666. }
  1667.  
  1668.